﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.BIM;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.LIB.YJKControls;
using YArchitech.Plumbing;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public partial class FrmCheckFourSprinkler : System.Windows.Forms.Form
	{
		public FrmCheckFourSprinkler(UIDocument uiDoc)
		{
			this.InitializeComponent();
			new YJKProcessTools().ShowInTaskbarChange(this);
			base.Icon = Resource.YArchitechIcon;
			this.doc = uiDoc.Document;
			this.sel = uiDoc.Selection;
			this.ptCalOperate = new SprinklerCalOperate();
		}

		private void FrmCheckFourSprinkler_Load(object sender, EventArgs e)
		{
			int sprinklerPara = this.ptCalOperate.GetSprinklerPara("CheckFourSprinklerDangerID");
			this.BindDangerLevelInfo();
			string text = new ModelAnalyser(this.doc).GetDangerLevel();
			if (text == null)
			{
				text = "中危险等级II";
			}
			int num = 0;
			while (num < this.cmbDangerLevel.Items.Count && !(this.cmbDangerLevel.Items[num] as Fire_Danger).DangerLevel.Equals(text))
			{
				num++;
			}
			this.cmbDangerLevel.SelectedIndex = num;
			this.BindParam(sprinklerPara);
		}

		private void BindDangerLevelInfo()
		{
			this.cmbDangerLevel.ValueMember = "Id";
			this.cmbDangerLevel.DisplayMember = "DangerLevel";
			this.cmbDangerLevel.DataSource = this.ptCalOperate.GetListFireDanger();
			this.cmbDangerLevel.SelectedValue = this.dangerId;
			this.dangerId = Convert.ToInt32(this.cmbDangerLevel.SelectedValue);
		}

		private void BindParam(int index)
		{
			this.lbSprinklerStress.Text = "10";
			switch (index)
			{
			case 0:
				this.lbWaterStrength.Text = "4";
				this.lbArea.Text = "160";
				return;
			case 1:
				this.lbWaterStrength.Text = "6";
				this.lbArea.Text = "160";
				return;
			case 2:
				this.lbWaterStrength.Text = "8";
				this.lbArea.Text = "160";
				return;
			case 3:
				this.lbWaterStrength.Text = "12";
				this.lbArea.Text = "260";
				return;
			default:
				this.lbWaterStrength.Text = "16";
				this.lbArea.Text = "260";
				return;
			}
		}

		private void btnOk_Click(object sender, EventArgs e)
		{
			if (this.hyTxtFlow.Text.Trim() == "" || this.hyTxtArea.Text.Trim() == "")
			{
				YJKMessageBox.Information("参数不能为空");
				return;
			}
			string text = (double.Parse(this.hyTxtFlow.Text) / 4.0).ToString();
			string text2 = this.hyTxtArea.Text;
			string text3 = this.lbWaterStrength.Text;
			this.lbTotalStress.Text = text;
			this.lbProtectArea.Text = text2;
			this.lbAverageWaterStrength.Text = Math.Round(double.Parse(text) / double.Parse(text2), 3).ToString();
			if (this.cmbDangerLevel.SelectedIndex < 3)
			{
				this.lbDesignWaterStrength.Text = (double.Parse(text3) * 0.85).ToString();
			}
			else
			{
				this.lbDesignWaterStrength.Text = text3;
			}
			if (double.Parse(this.lbAverageWaterStrength.Text) >= double.Parse(this.lbDesignWaterStrength.Text))
			{
				this.lbResult.Text = "故：满足要求";
				return;
			}
			this.lbResult.Text = "故：不满足要求";
		}

		private void btnCancel_Click(object sender, EventArgs e)
		{
			base.Close();
		}

		private void cmbDangerLevel_SelectedIndexChanged(object sender, EventArgs e)
		{
			this.dangerId = Convert.ToInt32(this.cmbDangerLevel.SelectedValue);
			int num = Convert.ToInt32(this.cmbDangerLevel.SelectedIndex);
			this.BindParam(num);
			this.ptCalOperate.SaveSprinklerPara((double)num, "CheckFourSprinklerDangerID");
		}

		private void btnSelectFourSprinkler_Click(object sender, EventArgs e)
		{
			this.iParam = 0;
			base.DialogResult = DialogResult.Abort;
		}

		private void btnProtectArea_Click(object sender, EventArgs e)
		{
			this.iParam = 1;
			base.DialogResult = DialogResult.Abort;
		}

		public void GetFourSprinklerFlow()
		{
			new FrmCheckFourSprinkler.SprinklersSelectionFilter();
			try
			{
				double num = 0.0;
				ElementSet elementSet = new ElementSet();
				TextNote textNote = null;
				IList<Element> sprinklers = this.GetSprinklers(ref elementSet, ref textNote);
				List<XYZ> list = new List<XYZ>();
				this.ErasePolygonLinesAndTextNote(ref elementSet, ref textNote);
				if (sprinklers.Count<Element>() != 4)
				{
					YJKMessageBox.Information("请选择四个喷头");
				}
				else
				{
					foreach (Element element in sprinklers)
					{
						LocationPoint locationPoint = element.Location as LocationPoint;
						list.Add(new XYZ(locationPoint.Point.X, locationPoint.Point.Y, 0.0));
						double num2 = FrmCheckFourSprinkler.ReadFlowFromSrpinkler(element);
						if (num2 == 0.0)
						{
							YJKMessageBox.Information("有未计算的喷头，请先进行喷淋计算。");
							return;
						}
						num += num2;
					}
					this.hyTxtFlow.Text = num.ToString("0.000");
					list = this.GetListXyz(list);
					double num3 = Math.Round(YJKRevitTools.CalArea(list) * 0.3048 * 0.3048, 3);
					if (num3 == 0.0)
					{
						YJKMessageBox.Information("请选择最不利作用面积内的四支可围合的喷头");
					}
					this.hyTxtArea.Text = (num3 * 2.0).ToString("0.000");
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
			}
		}

		private List<XYZ> GetListXyz(List<XYZ> listXyz)
		{
			XYZ xyz = new XYZ(0.0, 0.0, 0.0);
			foreach (XYZ xyz2 in listXyz)
			{
				xyz += xyz2;
			}
			xyz /= 4.0;
			xyz = new XYZ(xyz.X, xyz.Y, 0.0);
			for (int i = 0; i < listXyz.Count; i++)
			{
				for (int j = i; j < listXyz.Count; j++)
				{
					if (YJKRevitTools.GetTwoXYVectorAngle(new XYZ(0.0, 1.0, 0.0), listXyz[i] - xyz) > YJKRevitTools.GetTwoXYVectorAngle(new XYZ(0.0, 1.0, 0.0), listXyz[j] - xyz))
					{
						XYZ value = listXyz[i];
						listXyz[i] = listXyz[j];
						listXyz[j] = value;
					}
				}
			}
			return listXyz;
		}

		protected bool ErasePolygonLinesAndTextNote(ref ElementSet lines, ref TextNote textNote)
		{
			SubTransaction subTransaction = new SubTransaction(this.doc);
			subTransaction.Start();
			try
			{
				if (lines.Size > 0)
				{
					IEnumerator enumerator = lines.GetEnumerator();
					bool flag = enumerator.MoveNext();
					while (flag)
					{
						Element element = enumerator.Current as Element;
						if (element != null && this.doc.GetElement(element.Id) != null)
						{
							this.doc.Delete(element.Id);
						}
						flag = enumerator.MoveNext();
					}
					lines.Clear();
				}
				if (textNote != null)
				{
					this.doc.Delete(textNote.Id);
					textNote = null;
				}
				this.doc.Regenerate();
				subTransaction.Commit();
			}
			catch (Exception ex)
			{
				ex.ToString();
			}
			finally
			{
				if (subTransaction != null && (int)subTransaction.GetStatus() != 3)
				{
					subTransaction.RollBack();
				}
			}
			return true;
		}

		private IList<Element> GetSprinklers(ref ElementSet polygonLines, ref TextNote textNote)
		{
			IList<Element> list = new List<Element>();
			try
			{
				XYZ xyz = this.sel.PickPoint("请选择最不利作用面积内的四支可围合的喷头");
				XYZ xyz2 = new XYZ(xyz.X, xyz.Y, xyz.Z);
				XYZ xyz3 = new XYZ(xyz.X, xyz.Y, xyz.Z);
				List<XYZ> list2 = new List<XYZ>();
				list2.Add(xyz);
				for (;;)
				{
					try
					{
						xyz3 = this.sel.PickPoint("右键取消或ESC退出 /选择下一点:");
						if (xyz.IsAlmostEqualTo(xyz3))
						{
							YJKMessageBox.Error("不能选择两个重合的点！");
						}
						else
						{
							list2.Add(xyz3);
							DetailLine detailLine = YJKRevitTools.DrawDetailLine(this.doc, xyz, xyz3);
							polygonLines.Insert(detailLine);
							xyz = xyz3;
							if (list2.Count <= 2 || !xyz2.IsAlmostEqualTo(xyz3))
							{
								continue;
							}
							foreach (Element element in this.GetAllSprinklers())
							{
								LocationPoint locationPoint = element.Location as LocationPoint;
								double height = YJKRevitTools.GetFloorHeigh(this.doc, this.doc.ActiveView).height;
								double elevation = this.doc.ActiveView.GenLevel.Elevation;
								bool flag;
								if (height == 0.0)
								{
									flag = (locationPoint.Point.Z > elevation);
								}
								else
								{
									flag = (locationPoint.Point.Z > elevation && locationPoint.Point.Z < elevation + height);
								}
								if (YJKRevitTools.Contains(locationPoint.Point, list2) && flag)
								{
									list.Add(element);
								}
							}
							double num = Math.Round(YJKRevitTools.CalArea(list2) * 0.3048 * 0.3048, 3);
							XYZ origin = new XYZ(xyz2.X + 1.0, xyz2.Y - 1.0, xyz2.Z);
                            textNote = this.doc.GetTextNode(this.doc.ActiveView, origin, XYZ.BasisX, XYZ.BasisY, 0.24384000000000003, (TextAlignFlags)64, "面积：" + num + " m^2");
							this.doc.Regenerate();
						}
					}
					catch (Autodesk.Revit.Exceptions.OperationCanceledException ex)
					{
						ex.ToString();
						if (list2.Count > 2)
						{
							DetailLine detailLine2 = YJKRevitTools.DrawDetailLine(this.doc, xyz3, xyz2);
							polygonLines.Insert(detailLine2);
							foreach (Element element2 in this.GetAllSprinklers())
							{
								LocationPoint locationPoint2 = element2.Location as LocationPoint;
								if (YJKRevitTools.Contains(locationPoint2.Point, list2) && locationPoint2.Point.Z > this.doc.ActiveView.GenLevel.Elevation)
								{
									list.Add(element2);
								}
							}
							double num = Math.Round(YJKRevitTools.CalArea(list2) * 0.3048 * 0.3048, 3);
							XYZ origin2 = new XYZ(xyz2.X + 1.0, xyz2.Y - 1.0, xyz2.Z);
                            textNote = this.doc.GetTextNode(this.doc.ActiveView, origin2, XYZ.BasisX, XYZ.BasisY, 0.24384000000000003, (TextAlignFlags)64, "面积：" + num + " m^2");
							this.doc.Regenerate();
						}
					}
					catch (Exception ex2)
					{
						YJKMessageBox.Show(ex2.ToString());
						continue;
					}
					break;
				}
			}
			catch (Exception ex3)
			{
				ex3.ToString();
			}
			return list;
		}

		private List<Element> GetAllSprinklers()
		{
			List<Element> list = new List<Element>();
			foreach (Document document in ((IEnumerable<Document>)(from link in this.GetAllRevitLinkInstancesInDoc()
			select link.GetLinkDocument()).ToList<Document>()))
			{
				if (document != null)
				{
					FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
					list.AddRange(filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Sprinklers).ToElements());
				}
			}
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.doc, this.doc.ActiveView.Id);
			list.AddRange(filteredElementCollector2.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Sprinklers).ToElements());
			return list;
		}

		private List<RevitLinkInstance> GetAllRevitLinkInstancesInDoc()
		{
			IEnumerable<ElementId> enumerable = new FilteredElementCollector(this.doc).OfClass(typeof(RevitLinkInstance)).ToElementIds();
			List<RevitLinkInstance> list = new List<RevitLinkInstance>();
			foreach (ElementId elementId in enumerable)
			{
				Element element = this.doc.GetElement(elementId);
				if (!(element.GetType() != typeof(RevitLinkInstance)))
				{
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance != null)
					{
						list.Add(revitLinkInstance);
					}
				}
			}
			return list;
		}

		private static double ReadFlowFromSrpinkler(Element elem)
		{
			double result = 0.0;
			Schema schema = Schema.Lookup(FrmCheckFourSprinkler.guidOfSprinklerSchema);
			if (schema != null && schema.SchemaName == "SprinklerExtensibleData")
			{
				try
				{
					Entity entity = elem.GetEntity(schema);
					if (entity != null && entity.IsValid())
					{
						result = entity.Get<double>(schema.GetField("SprinklerFlow"), (Autodesk.Revit.DB.DisplayUnitType)64);
					}
				}
				catch
				{
				}
			}
			return result;
		}

		public void GetProtectArea()
		{
			ElementSet elementSet = new ElementSet();
			XYZ xyz = this.sel.PickPoint("请选择绘制线段的起点……");
			double num = 0.0;
			int num2 = 0;
			Line line = null;
			Line line2 = null;
			List<XYZ> list = new List<XYZ>();
			list.Add(xyz);
			for (;;)
			{
				try
				{
					XYZ xyz2 = this.sel.PickPoint("请选择绘制线段的终点……");
					if (!xyz.IsAlmostEqualTo(xyz2))
					{
						list.Add(xyz2);
						DetailLine detailLine = YJKRevitTools.DrawDetailLine(this.doc, xyz, xyz2);
						elementSet.Insert(detailLine);
						num2++;
						num += Math.Round((detailLine.Location as LocationCurve).Curve.Length * 0.3048, 3);
						if (num2 % 2 == 0)
						{
							line2 = ((detailLine.Location as LocationCurve).Curve as Line);
						}
						else if (num2 % 2 == 1)
						{
							line = ((detailLine.Location as LocationCurve).Curve as Line);
						}
						if (num2 >= 2 && line2 != null && line != null)
						{
							Math.Round(line.Length * 0.3048, 3);
							Math.Round(line2.Length * 0.3048, 3);
							line.Direction.AngleTo(line2.Direction);
							double num3 = Math.Round(YJKRevitTools.CalArea(list) * 0.3048 * 0.3048, 3);
							this.hyTxtArea.Text = num3.ToString();
						}
						xyz = xyz2;
						continue;
					}
					MessageBox.Show("不能选择两个重合的点！", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
				}
				break;
			}
			this.DeleteDatailLines(elementSet);
		}

		private bool DeleteDatailLines(ElementSet detailLines)
		{
			if (detailLines.Size < 1)
			{
				return false;
			}
			IEnumerator enumerator = detailLines.GetEnumerator();
			bool flag = enumerator.MoveNext();
			while (flag)
			{
				Element element = enumerator.Current as Element;
				this.doc.Delete(element.Id);
				flag = enumerator.MoveNext();
			}
			return true;
		}

		public static readonly Guid guidOfSprinklerSchema = new Guid("FCD17400-66EF-442C-A5ED-24953123520F");

		public int dangerId;

		private SprinklerCalOperate ptCalOperate;

		private Document doc;

		private Selection sel;

		public int iParam;

		private class SprinklersSelectionFilter : ISelectionFilter
		{
			public bool AllowElement(Element elem)
			{
				return elem is FamilyInstance && elem.Category.Id.IntegerValue == -2008099;
			}

			public bool AllowReference(Reference reference, XYZ position)
			{
				return false;
			}
		}
	}
}
